package mm.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class StringUtils {
		
	private static final Log LOG=LogFactory.getLog(StringUtils.class);

	public String buildJSON(Map map) { // TODO escape '"'
		StringBuffer sb=new StringBuffer();
		sb.append("{");
		for(Object key : map.keySet()){
			Object value=map.get(key);
			if(value==null)
				continue;
			if(value instanceof Map){
				Map subMap=(Map)value;
				for(Object subKey : subMap.keySet()){
					Object subValue = subMap.get(subKey);
					if(subValue!=null){
						sb.append("\""+key+"["+subKey+"]\":\""+subValue+"\",");
					}
				}
			}else{
				sb.append("\""+key+"\":\""+value+"\",");
			}
		}
		if(sb.length()>1)
			sb.deleteCharAt(sb.length()-1);
		sb.append("}");
		return sb.toString();
	}
	
	@SuppressWarnings("unchecked")
	public static List<Map> describe(String in){
		List<Map> list=new ArrayList<Map>();
		// check if 'in' exists
		if(in==null||in.length()<1)
			return list;
		String[] mapSs=in.split("\\|");
		// check if '|' exists
		if(mapSs==null||mapSs.length<1)
			return list;
		for (String mapS : mapSs) {
			// check if entity's length < 3 (like 'x:y')
			if(mapS.length()<3)
				continue;
			String[] kvSs=mapS.split(",");
			// check if kv exists
			if(kvSs==null||kvSs.length<1)
				continue;
			Map map=null;
			for (String kvS : kvSs) {
				int pos=kvS.indexOf(":");
				// check if field length < 3 and ":"'s postion < 1
				if(kvS.length()<3||pos<1)
					continue;
				String k=kvS.substring(0,pos);
				Object v=pos<kvS.length()-1?kvS.substring(kvS.indexOf(":")+1):null;
				if(map==null){
					map=new HashMap();
					list.add(map);
				}
				// kill blank
				if("".equals(v))
					v=null;
				if(v!=null&&((String)v).startsWith("{")&&((String)v).endsWith("}")){
					if(((String)v).length()>2){
						v=describe(((String)v).substring(1, ((String)v).length()-1));
					}else{
						// ignoring "{}"
						v=null;
					}
				}
				if(v!=null)
					map.put(k, v);
			}
		}
		return list;
	}
	
	@SuppressWarnings("unchecked")
	public static String build(Collection<Map> in){
		if(in==null||in.isEmpty())
			return "";
		StringBuffer sb=new StringBuffer();
		boolean entityStarted=false;
		for (Map<String, Object> map : in) {
			if(entityStarted)
				sb.append("|");
			boolean fieldStarted=false;
			for (String k : map.keySet()) {
				Object v=map.get(k);
				if(v==null)
					continue;
				if(fieldStarted)
					sb.append(",");
				String vS=null;
				if(v instanceof Collection){
					Collection<Map> c = null;
					try{
						c = (Collection<Map>) v;
					}catch(ClassCastException e){
						// ingore unknown collection
						LOG.error("Sub collections of a build-able collection must contain only map");
					}
					if(c==null||c.isEmpty())
						continue;
					vS="{"+build(c)+"}";
				}else{
					vS=escape((String)v);
				}
				sb.append(k+":"+vS);
				fieldStarted=true;
			}
			entityStarted=true;
		}
		return sb.toString();
	}

	private static String escape(String raw) {
		String out=raw;
		out=out.replaceAll("\\|", "_!001!_");
		out=out.replaceAll(",", "_!002!_");
		out=out.replaceAll("\\{", "_!003!_");
		out=out.replaceAll("\\}", "_!004!_");
		return out;
	}

	public static boolean matchWildcard(String in, String pattern) {
		String[] fragments=pattern.split("\\*");
		if(pattern.indexOf("*")>0&&in.indexOf(fragments[0])!=0)
			return false;
		for (String fragment : fragments) {
			if(fragment.length()<1)
				continue;
			int index=in.indexOf(fragment);
			if(index<0)
				return false;
			in=in.substring(index+fragment.length());
		}
		if(pattern.lastIndexOf("*")<pattern.length()-1&&in.length()>0)
			return false;
		return true;
	}

	public static String lowerCase(String in) {
		if(in==null||in.length()<1)
			return in;
		StringBuffer sb=new StringBuffer();
		for(int i=0; i<in.length(); i++){
			char c=in.charAt(i);
			if(c>64&&c<91){
				if(i>0)
					sb.append('_');
				sb.append((char)(c+32));
			}else{
				sb.append(c);
			}
		}
		return sb.toString();
	}

	// TODO var a="\r\n\t\\\"";
	public static String escapeJavascriptString(String in) {
		in=in.replaceAll("\r\n", "\\\\r\\\\n"); // TODO use 'replace' instead of 'replaceAll'?
		in=in.replaceAll("\t", "\\\\t");
		in=in.replaceAll("\"", "\\\\\"");
//		in=in.replaceAll("</script>", "<\"+\"\\\\/\"+\"script>");
		return in;
	}
	
	public static String toString(Map map){
		if(map==null)
			return null;
		StringBuffer sb = new StringBuffer("{");
		if(!map.isEmpty()){
			sb.append("\r\n");
			for(Iterator iter=map.keySet().iterator(); iter.hasNext(); ){
				Object key=iter.next();
				Object value=map.get(key);
				sb.append("\t"+key+" = "+value+",\r\n");
			}
		}
		sb.append("}\r\n");
		return sb.toString();
	}

}
